
package com.lucas.springboot_restful_api.util;

import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.springframework.beans.factory.annotation.Value;
import com.auth0.jwt.*;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PostMapping;

import java.util.*;

@Component
public class JwtToken {

    private static String jwtKey;
    private static Integer jwtExpiredIn;
    private static Integer defaultScope;

    @Value("${lucas.security.jwt-key:lucas}")
    public void setJwtKey(String jwtKey) {
        JwtToken.jwtKey = jwtKey;
    }

    @Value("${lucas.security.token-expired-in:7200}")
    public void setJwtExpiredIn(Integer jwtExpiredIn) {
        JwtToken.jwtExpiredIn = jwtExpiredIn;
    }

    @Value("${lucas.security.default-scope:8}")
    public void setDefaultScope(Integer defaultScope) {
        JwtToken.defaultScope = defaultScope;
    }

    public static Optional<Map<String, Claim>> getClaims(String token) {
        DecodedJWT decodedJWT;
        Algorithm algorithm = Algorithm.HMAC256(JwtToken.jwtKey);
        System.out.println(new Date());
        JWTVerifier jwtVerifier = JWT.require(algorithm).build();
        try {
            decodedJWT = jwtVerifier.verify(token);
        } catch (JWTVerificationException e) {
            e.printStackTrace();
            return Optional.empty();
        }
        return Optional.of(decodedJWT.getClaims());
    }

    public static String makeToken(String uid, Integer scope) {
        return JwtToken.getToken(uid, scope);
    }

    public static String makeToken(String uid) {
        return JwtToken.getToken(uid, JwtToken.defaultScope);
    }

    private static String getToken(String uid, Integer scope) {
        Algorithm algorithm = Algorithm.HMAC256(JwtToken.jwtKey);
        Map<String, Date> map = JwtToken.calculateExpiredIssues();
        return JWT.create()
                .withClaim("uid", uid)
                .withClaim("scope", scope)
                .withExpiresAt(map.get("expiredTime"))
                .withIssuedAt(map.get("now"))
                .sign(algorithm);
    }

    private static Map<String, Date> calculateExpiredIssues() {
        Map<String, Date> map = new HashMap<>();
        Calendar calendar = Calendar.getInstance();
        Date now = calendar.getTime();
        calendar.add(Calendar.SECOND, JwtToken.jwtExpiredIn);
        map.put("now", now);
        map.put("expiredTime", calendar.getTime());
        return map;
    }

    @PostMapping("/verify")
    public static Boolean verifyToken(String token) {
        try {
            Algorithm algorithm = Algorithm.HMAC256(JwtToken.jwtKey);
            JWTVerifier verifier = JWT.require(algorithm).build();
            verifier.verify(token);
        } catch (JWTVerificationException e) {
            return false;
        }
        return true;

    }

}
